package com.zsc.wxapp.services.impl;

import com.zsc.wxapp.entity.PythonResponse;
import com.zsc.wxapp.entity.Res;
import com.zsc.wxapp.entity.Product;
import com.zsc.wxapp.entity.vo.ProductVO;
import com.zsc.wxapp.entity.vo.RecognitionVO;
import com.zsc.wxapp.exservices.Remote2;
import com.zsc.wxapp.services.ProcessedDataService;
import com.zsc.wxapp.utils.AliOssUtil;
import com.zsc.wxapp.utils.BeanUtils;
import com.zsc.wxapp.utils.ImageUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ProcessedDataServiceImpl implements ProcessedDataService {

    @Resource
    private Remote2 remote2;
//    @Resource
//    private ImageUtil imageUtil;

    /**
     * 处理python端返回的数据
     * @param pythonResponse
     * @param url
     * @param downloadImage
     * @return
     */
    @Override
    public RecognitionVO processedData(PythonResponse pythonResponse, String url, String downloadImage) {
        RecognitionVO result = new RecognitionVO();
        List<Res> resList = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        List<ProductVO> resultPrice = new ArrayList<>();
        List<ProductVO> resLoseTags = new ArrayList<>();
        Integer recognitionCount = 0;
        Integer total = 1;

        // 获取到python返回的数据
        List<String> loseTagList = pythonResponse.getResLoseTag();
        List<List<String>> res = pythonResponse.getRes();
        log.info("识别不到的标签：{}", loseTagList);

        if (!res.isEmpty()) {
            // 处理识别结果res
            for (int i = 0; i < res.size(); i++) {
                List<String> re = res.get(i);
                if ("false".equals(re.get(2))) {
                    log.warn("识别错误，本次识别的数据是：{}", re);
                    continue;
                }
                // 插入识别结果
                BigDecimal price = BigDecimal.ZERO;
                if (re.get(1) != null) {
                    log.info("识别到的价格是：{}", re.get(1));
                    try {
                        price = new BigDecimal(re.get(1));
                    } catch (NumberFormatException e) {
                        // 处理无法转换的情况
                        log.warn("无法将 " + re.get(1) + " 转换为数字");
                        price = BigDecimal.ZERO;
                    }
                }

                Res r = Res.builder()
                        .productName(re.get(0))
                        .price(price)
                        .trueOrFalse(re.get(2))
                        .bbox(getBbox(re.get(3)))
                        .build();
                resList.add(r);
                recognitionCount++;
                nameList.add(re.get(0));
            }

            log.info("识别结果resList：{}", resList);

            // 处理从远程数据库获取到的价格数据
            for (String s : nameList) {
                Product product = remote2.getCigaretteByName(s);
                ProductVO productVO = new ProductVO();
                BeanUtils.copyProperties(product, productVO);
                resultPrice.add(productVO);
            }
        }

        // 对缺失价签的数据去重
        loseTagList = removeDuplicateTags(resList, loseTagList);

        if (!loseTagList.isEmpty()) {
            // 处理没有价签数据的信息
            total = 0;
            for (int i = 0; i < loseTagList.size(); i++) {
                if (i == loseTagList.size() - 1) {
                    // 处理最后一个元素
                    try {
                        total = Integer.valueOf(loseTagList.get(i));
                        log.info("识别到的的价签数量，total：{}", total);
                        continue;
                    } catch (NumberFormatException e) {
                        log.warn("无法将 " + loseTagList.get(i) + " 转换为数字");
                        throw new RuntimeException("无法将 " + loseTagList.get(i) + " 转换为数字");
                    }
                }
                Product product = remote2.getCigaretteByName(loseTagList.get(i));
                ProductVO productVO = ProductVO.builder()
                        .productName(loseTagList.get(i))
                        .directRetailPrice(product.getDirectRetailPrice())
                        .productCode(product.getProductCode())
                        .packageQty(product.getPackageQty())
                        .build();
                resLoseTags.add(productVO);
            }
        }

        if (res.isEmpty() && loseTagList.isEmpty()) {
            return null;
        }

        //计算明码标价率
        BigDecimal priceRate = getPriceRate(recognitionCount, total);

        // 判断是否返回图片
        if (downloadImage.equals("true")) {
            String markedImage = pythonResponse.getMarkedImage();
            Integer index = markedImage.indexOf("?");
            if (index != -1) {
                markedImage = markedImage.substring(0, index);
            }

            url = url.replace("jialitong.site", "xxgxq.club");
            markedImage = markedImage.replace("jialitong.site", "xxgxq.club");

            result.setUrlMarkedImage(markedImage);
            result.setUrlImage(url);
        }

        result.setPriceRate(priceRate);
        result.setRes(resList);
        result.setProducts(resultPrice);
        result.setResLoseTag(resLoseTags);

        return result;
    }

    public BigDecimal getPriceRate(Integer recognitionCount, Integer total) {
        BigDecimal result = BigDecimal.ZERO;
        try {
            if (recognitionCount != 0 && total != 0 && total != null) {
                BigDecimal a = BigDecimal.valueOf(recognitionCount);
                BigDecimal b = BigDecimal.valueOf(total);
                result = a.divide(b, 2, RoundingMode.HALF_UP);
            }
        } catch (RuntimeException e) {
            log.error("计算明码标价率时发生异常：" + e.getMessage());
            log.error("recognitionCount:{}", recognitionCount);
            log.error("total:{}", total);
            return result;
        }
        return result;
    }

    public List<Integer> getBbox(String bboxStr) {
        String trimmedStr = bboxStr.substring(1, bboxStr.length() - 1);

        // 使用逗号分割字符串
        String[] parts = trimmedStr.split(", ");

        // 创建一个空的ArrayList
        List<Integer> list = new ArrayList<>();

        // 遍历字符串数组并转换为整数
        for (String part : parts) {
            int number = Integer.parseInt(part);
            list.add(number);
        }

        return list;
    }

    /**
     * 从URL下载图片，转成base64位数据
     * @param imageUrl
     * @return
     * @throws Exception
     */
    private String downloadImageFromUrl(String imageUrl) throws Exception {
        // 创建URL对象
        URL url = new URL(imageUrl);

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.connect();

        // 检查响应代码
        int responseCode = connection.getResponseCode();
        if (responseCode != 200) {
            throw new RuntimeException("Failed to download image, HTTP response code: " + responseCode);
        }

        // 读取输入流
        InputStream inputStream = connection.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }

        // 关闭流
        inputStream.close();
        connection.disconnect();

        // 转成base64位数据
        return Base64.getEncoder().encodeToString(baos.toByteArray());
    }


    /**
     * 处理python端返回的数据，没有计算明码标价率
     * @param pythonResponse
     * @param url
     * @param downloadImage
     * @return
     */
    @Override
    public RecognitionVO processedDataWithoutPriceRate(PythonResponse pythonResponse, String url, String downloadImage) {
        RecognitionVO result = new RecognitionVO();
        List<Res> resList = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        List<ProductVO> resultPrice = new ArrayList<>();
        List<ProductVO> resLoseTags = new ArrayList<>();
        Integer recognitionCount = 0;
        Integer total = 1;

        // 获取到python返回的数据
        List<String> loseTagList = pythonResponse.getResLoseTag();
        List<List<String>> res = pythonResponse.getRes();
        log.info("缺失价签数据resLoseTag为：{}", loseTagList);

        if (!res.isEmpty() || !res.equals("")) {
            // 处理识别结果res
            for (int i = 0; i < res.size(); i++) {
                List<String> re = res.get(i);
                if ("false".equals(re.get(2))) {
                    log.warn("识别错误，本次识别的数据是：{}", re);
                    continue;
                }
                // 插入识别结果
                BigDecimal price = BigDecimal.ZERO;
                if (re.get(1) != null) {
                    log.info("识别到的数据是：{}", re);
                    try {
                        price = new BigDecimal(re.get(1));
                    } catch (NumberFormatException e) {
                        // 处理无法转换的情况
                        log.warn("无法将 " + re.get(1) + " 转换为数字");
                        price = BigDecimal.ZERO;
                    }
                }

                String name = re.get(0);
                //转成unicode编码
//                try {
//                    name = URLEncoder.encode(name, String.valueOf(StandardCharsets.UTF_8));
//                } catch (UnsupportedEncodingException e) {
//                    log.error("编码失败，本次要编码的内容是：{}", name);
//                    name = "识别失败";
//                }

                Res r = Res.builder()
                        .productName(name)
                        .price(price)
                        .trueOrFalse(re.get(2))
                        .bbox(getBbox(re.get(3)))
                        .build();
                resList.add(r);
                recognitionCount++;
                nameList.add(re.get(0));
            }

//            log.info("识别结果resList：{}", resList);

            // 处理从远程数据库获取到的价格数据
            for (String s : nameList) {
                Product product = remote2.getCigaretteByName(s);
                ProductVO productVO = new ProductVO();
                BeanUtils.copyProperties(product, productVO);
                resultPrice.add(productVO);
            }
        }

        // 对缺失价签的数据去重
        loseTagList = removeDuplicateTags(resList, loseTagList);

        if (!loseTagList.isEmpty()) {
            // 处理没有价签数据的信息
            total = 0;
            for (int i = 0; i < loseTagList.size(); i++) {
                if (i == loseTagList.size() - 1) {
                    // 处理最后一个元素
                    try {
                        total = Integer.valueOf(loseTagList.get(i));
                        log.info("识别到的的价签数量，total：{}", total);
                        continue;
                    } catch (NumberFormatException e) {
                        log.warn("无法将 " + loseTagList.get(i) + " 转换为数字");
                        throw new RuntimeException("无法将 " + loseTagList.get(i) + " 转换为数字");
                    }
                }
                Product product = remote2.getCigaretteByName(loseTagList.get(i));

                if (product.getProductCode() == null) {
                    log.warn("没有找到名为 {} 的卷烟信息", loseTagList.get(i));
                } else {
                    // 隔离非法的卷烟名称加入到集合中
                    ProductVO productVO = ProductVO.builder()
                            .productName(loseTagList.get(i))
                            .directRetailPrice(product.getDirectRetailPrice())
                            .productCode(product.getProductCode())
                            .packageQty(product.getPackageQty())
                            .build();
                    resLoseTags.add(productVO);
                }
            }
        }

        if (res.isEmpty() && loseTagList.isEmpty()) {
            return null;
        }

        //计算明码标价率
//        BigDecimal priceRate = getPriceRate(recognitionCount, total);

        // 判断是否返回图片
        if (downloadImage.equals("true")) {
            String markedImage = pythonResponse.getMarkedImage();
            Integer index = markedImage.indexOf("?");
            if (index != -1) {
                markedImage = markedImage.substring(0, index);
            }

            url = url.replace("jialitong.site", "xxgxq.club");
            markedImage = markedImage.replace("jialitong.site", "xxgxq.club");
            result.setUrlMarkedImage(markedImage);
            result.setUrlImage(url);
        }

        result.setRes(resList);
        result.setProducts(resultPrice);
        result.setResLoseTag(resLoseTags);
        result.setUrlImage(url);

        return result;
    }

    /**
     * 去重
     * @param res
     * @param loseTagList
     * @return
     */
    private List<String> removeDuplicateTags(List<Res> res, List<String> loseTagList) {
        Set<String> productNames = res.stream()
                .map(Res::getProductName)
                .collect(Collectors.toSet());

//        log.info("productNames：{}", productNames);

        loseTagList.removeAll(productNames);

//        log.info("removeDuplicateTags：{}", loseTagList);
        return loseTagList;
    }

}
